﻿using pcDAL;
using pcObjectLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace pcBLL
{
    //class _PasswordBLL
    //{
    //    public PasswordBLL()
    //    {
    //        this.Minimum = DefaultMinimum;
    //        this.Maximum = DefaultMaximum;
    //        this.ConsecutiveCharacters = false;
    //        this.RepeatCharacters = true;
    //        this.ExcludeSymbols = false;
    //        this.Exclusions = null;

    //        rng = new RNGCryptoServiceProvider();
    //    }

    //    protected int GetCryptographicRandomNumber(int lBound, int uBound)
    //    {
    //        // Assumes lBound >= 0 && lBound < uBound

    //        // returns an int >= lBound and < uBound

    //        uint urndnum;
    //        byte[] rndnum = new Byte[4];
    //        if (lBound == uBound - 1)
    //        {
    //            // test for degenerate case where only lBound can be returned

    //            return lBound;
    //        }

    //        uint xcludeRndBase = (uint.MaxValue -
    //            (uint.MaxValue % (uint)(uBound - lBound)));

    //        do
    //        {
    //            rng.GetBytes(rndnum);
    //            urndnum = System.BitConverter.ToUInt32(rndnum, 0);
    //        } while (urndnum >= xcludeRndBase);

    //        return (int)(urndnum % (uBound - lBound)) + lBound;
    //    }

    //    protected char GetRandomCharacter()
    //    {
    //        int upperBound = pwdCharArray.GetUpperBound(0);

    //        if (true == this.ExcludeSymbols)
    //        {
    //            upperBound = PasswordBLL.UBoundDigit;
    //        }

    //        int randomCharPosition = GetCryptographicRandomNumber(
    //            pwdCharArray.GetLowerBound(0), upperBound);

    //        char randomChar = pwdCharArray[randomCharPosition];

    //        return randomChar;
    //    }

    //    public string Generate()
    //    {
    //        // Pick random length between minimum and maximum   

    //        int pwdLength = GetCryptographicRandomNumber(this.Minimum,
    //            this.Maximum);

    //        StringBuilder pwdBuffer = new StringBuilder();
    //        pwdBuffer.Capacity = this.Maximum;

    //        // Generate random characters
    //        char lastCharacter, nextCharacter;

    //        // Initial dummy character flag
    //        lastCharacter = nextCharacter = '\n';

    //        for (int i = 0; i < pwdLength; i++)
    //        {
    //            nextCharacter = GetRandomCharacter();

    //            if (false == this.ConsecutiveCharacters)
    //            {
    //                while (lastCharacter == nextCharacter)
    //                {
    //                    nextCharacter = GetRandomCharacter();
    //                }
    //            }

    //            if (false == this.RepeatCharacters)
    //            {
    //                string temp = pwdBuffer.ToString();
    //                int duplicateIndex = temp.IndexOf(nextCharacter);
    //                while (-1 != duplicateIndex)
    //                {
    //                    nextCharacter = GetRandomCharacter();
    //                    duplicateIndex = temp.IndexOf(nextCharacter);
    //                }
    //            }

    //            if ((null != this.Exclusions))
    //            {
    //                while (-1 != this.Exclusions.IndexOf(nextCharacter))
    //                {
    //                    nextCharacter = GetRandomCharacter();
    //                }
    //            }

    //            pwdBuffer.Append(nextCharacter);
    //            lastCharacter = nextCharacter;
    //        }

    //        if (null != pwdBuffer)
    //        {
    //            return pwdBuffer.ToString();
    //        }
    //        else
    //        {
    //            return String.Empty;
    //        }
    //    }

    //    public string Exclusions
    //    {
    //        get { return this.exclusionSet; }
    //        set { this.exclusionSet = value; }
    //    }

    //    public int Minimum
    //    {
    //        get { return this.minSize; }
    //        set
    //        {
    //            this.minSize = value;
    //            if (PasswordBLL.DefaultMinimum > this.minSize)
    //            {
    //                this.minSize = PasswordBLL.DefaultMinimum;
    //            }
    //        }
    //    }

    //    public int Maximum
    //    {
    //        get { return this.maxSize; }
    //        set
    //        {
    //            this.maxSize = value;
    //            if (this.minSize >= this.maxSize)
    //            {
    //                this.maxSize = PasswordBLL.DefaultMaximum;
    //            }
    //        }
    //    }

    //    public bool ExcludeSymbols
    //    {
    //        get { return this.hasSymbols; }
    //        set { this.hasSymbols = value; }
    //    }

    //    public bool RepeatCharacters
    //    {
    //        get { return this.hasRepeating; }
    //        set { this.hasRepeating = value; }
    //    }

    //    public bool ConsecutiveCharacters
    //    {
    //        get { return this.hasConsecutive; }
    //        set { this.hasConsecutive = value; }
    //    }

    //    private const int DefaultMinimum = 6;
    //    private const int DefaultMaximum = 10;
    //    private const int UBoundDigit = 61;

    //    private RNGCryptoServiceProvider rng;
    //    private int minSize;
    //    private int maxSize;
    //    private bool hasRepeating;
    //    private bool hasConsecutive;
    //    private bool hasSymbols;
    //    private string exclusionSet;
    //    private readonly char[] pwdCharArray = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()-_=+[]{}\\|;:'\",<.>/?".ToCharArray();                                        
    //}

    public class PasswordBLL
    {
        public static bool ValidatePassword(UserObjLibrary user, string Password)
        {
            return user.passwordHash == EncodePassword(Password, user.passwordSalt);
        }

        public static int ValidatePassword(string userName, string Password, string ipAddress, string MacAddress)
        {
            UserDAL ud = new UserDAL();
            UserObjLibrary user = ud.Details(userName:userName);
            user.lastActivity_ip = ipAddress;
            user.lastActive_MAC_address = MacAddress;
            if (user != null && user.userId > 0)
                ud.LogInActivity(user);
            if(user == null || user.userId < 1)
                return -1;
            return ValidatePassword(user,Password) ? user.userId : -2;
        }

        public static string GenerateSalt()
        {
            byte[] buf = new byte[16];
            (new RNGCryptoServiceProvider()).GetBytes(buf);
            return Convert.ToBase64String(buf);
        }

        public static string EncodePassword(string pass, string salt)
        {
            try
            {
                byte[] bytes = Encoding.Unicode.GetBytes(pass);
                byte[] src = Convert.FromBase64String(salt);
                byte[] dst = new byte[src.Length + bytes.Length];
                byte[] inArray = null;
                Buffer.BlockCopy(src, 0, dst, 0, src.Length);
                Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);

                HashAlgorithm algorithm = HashAlgorithm.Create("SHA512");
                inArray = algorithm.ComputeHash(dst);

                return Convert.ToBase64String(inArray);
            }
            catch (Exception ex)
            {
                // This gets thrown if the salt is invalid
                return "--Invalid--";   // Any non empty value is fine to make sure the match fails
            }
        }
    }
}
